package wps.mojo.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.FalseFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.lang.StringUtils;
import org.codehaus.plexus.resource.ResourceManager;
import org.codehaus.plexus.resource.loader.FileResourceCreationException;
import org.codehaus.plexus.resource.loader.ResourceNotFoundException;

/**
 * @Author : <a href="mailto:Juanyong.zhang@carefirst.com">Cham
 *         Juanyong.zhang</a>
 * @Date : Apr 14, 2011
 */
public abstract class ResourceLocator {
	public static final String FILE_URL_PREFIX = "file:";
	public static final String URL_PROTOCOL_JAR = "jar";
	public static final String URL_PROTOCOL_ZIP = "zip";
	public static final String URL_PROTOCOL_WSJAR = "wsjar";
	public static final String URL_PROTOCOL_CODE_SOURCE = "code-source";
	public static final String JAR_URL_SEPARATOR = "!/";

	public static boolean isJarURL(URL url) {
		String protocol = url.getProtocol();
		return (URL_PROTOCOL_JAR.equals(protocol)
				|| URL_PROTOCOL_ZIP.equals(protocol)
				|| URL_PROTOCOL_WSJAR.equals(protocol) || (URL_PROTOCOL_CODE_SOURCE
				.equals(protocol) && url.getPath().contains(JAR_URL_SEPARATOR)));
	}

	public static URL extractJarFileURL(URL jarUrl)
			throws MalformedURLException {
		String urlFile = jarUrl.getFile();
		int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
		if (separatorIndex != -1) {
			String jarFile = urlFile.substring(0, separatorIndex);
			try {
				return new URL(jarFile);
			} catch (MalformedURLException ex) {
				if (!jarFile.startsWith("/")) {
					jarFile = "/" + jarFile;
				}
				return new URL(FILE_URL_PREFIX + jarFile);
			}
		} else {
			return jarUrl;
		}
	}

	public static void copyJarDirectoryToDirectory(
			ResourceManager resourceManager, String srcURL, String destDir)
			throws IOException, ResourceNotFoundException,
			FileResourceCreationException {
		URL url = new URL(srcURL);
		if (isJarURL(url)) {
			URL jarURL = extractJarFileURL(url);
			File tempJar = File.createTempFile("tmp", ".jar");
			String keyPattern = StringUtils.substring(srcURL,
					srcURL.indexOf(JAR_URL_SEPARATOR) + 2);
			OutputStream jarOs = new FileOutputStream(tempJar);
			jarOs.write(IOUtils.toByteArray((InputStream) jarURL.getContent()));

			JarFile jar = new JarFile(tempJar);
			Enumeration<JarEntry> jarEntries = jar.entries();
			while (jarEntries.hasMoreElements()) {
				JarEntry jarEntry = jarEntries.nextElement();
				String entiryName = jarEntry.getName();

				if (entiryName.contains(keyPattern) && !jarEntry.isDirectory()) {
					String jarEntryURL = StringUtils.remove(srcURL, keyPattern)
							+ entiryName;

					File jarEntryFile = resourceManager
							.getResourceAsFile(jarEntryURL);

					String fileName = StringUtils.split(entiryName)[StringUtils
							.split(entiryName).length - 1];
					String folder = StringUtils.remove(entiryName, fileName);

					FileUtils.copyFile(jarEntryFile, new File(destDir + "/"
							+ folder + fileName));
				}
			}

		}
	}

	public static File getOnlyFile(File basedir, String fileName,
			boolean recursive) {
		File found = null;
		Collection<File> founds = FileUtils.listFiles(basedir, FileFilterUtils
				.nameFileFilter(fileName), (recursive ? TrueFileFilter.INSTANCE
				: FalseFileFilter.INSTANCE));
		found = founds.toArray(new File[founds.size()])[0];
		return found;
	}

	public static Collection<File> getFiles(File basedir, String fileName,
			boolean recursive) {

		return FileUtils.listFiles(basedir, FileFilterUtils
				.nameFileFilter(fileName), (recursive ? TrueFileFilter.INSTANCE
				: FalseFileFilter.INSTANCE));
	}

	public static Collection<File> searchFiles(File basedir, String fileName,
			boolean recursive, boolean ignoreCase) {
		final String ALL_MATCH = ".*[\\w]?";
		String regex = ALL_MATCH + fileName + ALL_MATCH;

		return FileUtils
				.listFiles(
						basedir,
						new RegexFileFilter(ignoreCase ? Pattern.compile(regex,
								Pattern.CASE_INSENSITIVE) : Pattern
								.compile(regex)),
						(recursive ? TrueFileFilter.INSTANCE
								: FalseFileFilter.INSTANCE));
	}

	public static Properties loadProperties(String filePath)
			throws FileNotFoundException, IOException {
		Properties properties = new Properties();

		properties.load(new FileInputStream(filePath));

		return properties;
	}

	public static Properties loadProperties(File file)
			throws FileNotFoundException, IOException {
		Properties properties = new Properties();

		properties.load(new FileInputStream(file));

		return properties;
	}
}